﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using ecdl.demo.model.expression;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Wordprocessing;
using DocumentFormat.OpenXml.Packaging;

namespace ecdl.demo.model.expression {
    public abstract class WordExpression : Expression {

        public override ExpressionState Evaluate(ExpressionContext context) {
            if (context.HasContext<OpenXmlElement>()) {
                return Evaluate(context.ContextAsList<OpenXmlElement>());

            } else if (context.HasContext<IEnumerable<OpenXmlElement>>()) {
                return Evaluate(context.GetContext<IEnumerable<OpenXmlElement>>());

            }else if (context.HasContext<WordprocessingDocument>()){
                return Evaluate(context.GetContext<WordprocessingDocument>().MainDocumentPart.RootElement);
            
            } else {
                return FailInvalidContext();
            }
        }

        protected ExpressionState FailInvalidContext() {
            return Fail(String.Format("Die %s kann nur im Kontext eines Worddokuments verwendet werden.", this.GetType().Name));
        }

        protected IEnumerable<Paragraph> GetAllParagraphs(IEnumerable<OpenXmlElement> elements) {
            var paragraphs = new List<Paragraph>();
            foreach (var container in elements) {
                paragraphs.AddRange(GetAllParagraphs(container));
            }
            return paragraphs;
        }

        protected IEnumerable<Paragraph> GetAllParagraphs(OpenXmlElement element) {
            return element.Descendants<Paragraph>();
        }

        protected IEnumerable<T> Descendents<T>(IEnumerable<OpenXmlElement> elements) where T : OpenXmlElement {
            var descendents = new List<T>();
            foreach (var element in elements) {
                descendents.AddRange(element.Descendants<T>());
            }
            return descendents;
        }

        protected string GetText(Paragraph p) {
            StringBuilder buffer = new StringBuilder();
            foreach (var textElement in p.Descendants<Text>()) {
                buffer.Append(textElement.InnerText);
            }
            return buffer.ToString();
        }

        protected abstract ExpressionState Evaluate(IEnumerable<OpenXmlElement> contextElements);
    }
}
